---
menu: Non-active Proposals
name: File (Explainer)
pathToResearch: /components/file.research
layout: ../../layouts/ComponentLayout.astro
---

import '../../styles/spec.css'
import FileAnatomy from '../../components/file-anatomy'

## Overview

The `<input type="file">` (or file input) element is a control that provides
the user with the ability to select local files.

### Background

The file input allows users to upload one or multiple files, which may or may
not be part of a form submission.

Currently, this control is the only way access to access a user's filesystem.

### Use Cases

The file input is widely used across the web. Examples include attaching
documents to a job or visa application, and uploading multimedia content to
cloud storage services.

### Non-goals

The file input does not provide a way to programmatically invoke access to a
user's filesystem, other than invoking `showPicker()`.

### Features

This control invokes a prompt to the user requesting that the user specify one
or more files to upload. Once selected, the prompt collapses and input is
updated with the selected files.

### Risks and Challenges

There are no risks or challenges presented as a part of this proposal.

### Prior Art/Examples

- [Ant Design](https://ant.design/components/upload/)
- [Bootstrap](https://getbootstrap.com/docs/5.3/forms/form-control/#file-input)
- [Carbon](https://www.carbondesignsystem.com/components/file-uploader/usage/)
- [Evergreen](https://evergreen.segment.com/components/filepicker)
- [KoliBri](https://public-ui.github.io/docs/components/input-file)
- [Materialise](https://materializecss.com/text-inputs.html)
- [MOJ](https://moj-design-system.herokuapp.com/components/multi-file-upload)

Examples can also be found within platforms like GitHub (attaching binaries to
a release), along with many government sites.

## Design

The file input consists of two parts: a button, and a label. Clicking the
button invokes the file selection prompt.

### API

## Properties and Attributes

| Attribute Name                                                                        | Type                                                                      | Default Value    | Description                                                                                                                                                                 |
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`accept`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept)       | `string`                                                                  | Empty `string`   | One or more unique file type specifiers describing file types to allow                                                                                                      |
| [`capture`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/capture)     | `string`                                                                  | `null`           | What source to use for capturing image or video data (`user` or `environment`)                                                                                              |
| `value`                                                                               | [`DOMString`](https://developer.mozilla.org/en-US/docs/Web/API/DOMString) | Empty `string`   | A `DOMString` that represents the path to the selected file(s). If the user selected multiple files, the value represents the first file in the list of files they selected |
| [`files`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#files) | [`FileList`](https://developer.mozilla.org/en-US/docs/Web/API/FileList)   | Empty `FileList` | A `FileList` listing the chosen files                                                                                                                                       |
| [`multiple`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/multiple)   | `boolean`                                                                 | `false`          | A `boolean` which, if present, indicates that the user may choose more than one file                                                                                        |

## Methods

| Signature            | Description                                                           |
| ---------------------| ----------------------------------------------------------------------|
| `showPicker(): void` | Triggers the system file picker UI to show. Requires user activation. |

## Events

| Event Name | Detail Type | Bubbles | Composed | Cancellable | Dispatch Behavior                                            |
| ---------- | ----------- | ------- | -------- | ----------- | ------------------------------------------------------------ |
| `cancel`   | none        | `true`  | `true`   | `false`     | Fired when the when the user does not change their selection.|
| `change`   | none        | `true`  | `true`   | `false`     | Fired when the input's `value` is commited by the user.      |
| `input`    | none        | `true`  | `true`   | `false`     | Fired when the input's `value` changes.                      |

### Anatomy

#### Diagram

<FileAnatomy />

#### DOM Structure

```html
<host>
  <slot name="file-selector-button">
    <button part="file-selector-button"></button>
  </slot>
  <slot name="label">
    <span part="label"></span>
  </slot>
</host>
```

#### Slots

| Slot Name              | Description                                                                           | Fallback Content              |
| ---------------------- | ------------------------------------------------------------------------------------- | ----------------------------- |
| `file-selector-button` | Invokes the file selection prompt.                                                    | A button element is provided. |
| `label`                | Indicates if a file input is waiting for file selection, or if it has selected files. | A span element is provided.  |

#### CSS Parts

| Part Name              | Description                                           |
| ---------------------- | ----------------------------------------------------- |
| `file-selector-button` | The controls button.                                  |
| `label`                | The controls label, indicating file selection status. |

---

## Behavior

### States and Interactions

When the input is invoked, the file selection prompt will limit the user to
selecting files that match the `accept` attribute, and the user will be limited
to selecting a single file unless the `multiple` attribute is `true`.

When a file are selected, the `label` updates to show the filename. When set to
`multiple`, the number of selected files is shown instead of a filename.

If a user cancels the prompt (choosing not to select a file), the input shows
the default (no selection) state. This also clears any previously selected
files.

#### Drag and drop

Users may also drag and drop files onto the input, where the drop target is the
containing element.

#### Accessibility

The file input should be focusable via keyboard navigation (tab).

#### Keyboard Navigation and Focus

When no files have been selected, there will be one tap stop for the entire control
([resolution](https://github.com/openui/open-ui/issues/107#issuecomment-646344160)).

#### Form Input

The file input integrates with forms, accepting the `required` attribute for
validation.

#### Use with Assistive Technology

The `openui-file` component should appear as a `button` (ARIA role) along with
a `label` representing the current selection state.

As with other form controls, a `label` should be used to give context to this
control.

### Globalization

The positions of the button and label should be reversed for languages written
RTL (right-to-left).

### Security

The `<input type="file">` element doesn't allow applications access to the
filesystem, and the value is prefixed with a [fake path](https://html.spec.whatwg.org/multipage/input.html#fakepath-srsly).

## Performance

There are no current performance concerns for the file input.

## Dependencies

No third party dependencies are required.

### Platform Requirements

To implement a custom file input, a developer must create a hidden
`<input type="file">` element, and call `showPicker()` on that element to invoke
that input's behaviour.

The [File System Access API](https://wicg.github.io/file-system-access/#local-filesystem)
will allow for implementations of file input controls without the above
workaround.

### Tooling

No additional tooling is required for the file input.

---

## Resources

- [MDN Reference on the current &lt;input type="file"&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file)
- [MDN Reference on the File API](https://developer.mozilla.org/en-US/docs/Web/API/File)
- [WHATWG Living Standard on &lt;input type="file"&gt;](<https://html.spec.whatwg.org/multipage/input.html#file-upload-state-(type=file)>)

## Next steps

Some file input implementations list selected files for the user to review,
deselect/remove, and possibly rename. There is no specification for this
behaviour.
